
import java.util.concurrent.Exchanger;

public class ExchangerTest {
    // Exchanger Exchanger 类表示一种两个线程可进行相互交换对象的汇合点
    // 只能用于两个线程之间，并且两个线程必须都到达汇合点才会进行数据交换
    public static void main(String[] args) {
        Exchanger<String> exchanger = new Exchanger<>();
        ExchangerRunnable exchangerRunnable1 = new ExchangerRunnable(exchanger,"A");
        ExchangerRunnable exchangerRunnable2 = new ExchangerRunnable(exchanger,"B");
        Exchanger<String> exchanger2 = new Exchanger<>();
        ExchangerRunnable exchangerRunnable3 = new ExchangerRunnable(exchanger2,"C");
        ExchangerRunnable exchangerRunnable4 = new ExchangerRunnable(exchanger2,"D");

        new Thread(exchangerRunnable1).start();
        new Thread(exchangerRunnable2).start();
        new Thread(exchangerRunnable3).start();
        new Thread(exchangerRunnable4).start();
    }
}

class ExchangerRunnable implements Runnable {
    Exchanger<String> exchanger = null;
    String object = null;

    public ExchangerRunnable(Exchanger<String> exchanger, String obj) {
        this.exchanger = exchanger;
        this.object = obj;
    }

    @Override
    public void run() {
        Object previous = this.object;
        System.out.println(Thread.currentThread().getName()
                + "交换前  previous = " + previous);
        try {
            if ("C".equals(previous)) {
                Thread.sleep(3000);
                System.out.println(Thread.currentThread().getName() + "对数据A的处理耗时3秒");
            } else if ("D".equals(previous)) {

                Thread.sleep(4000);
                System.out.println(Thread.currentThread().getName() + "对数据A的处理耗时3秒");

            }
            else if ("A".equals(previous)) {

                Thread.sleep(3000);
                System.out.println(Thread.currentThread().getName() + "对数据A的处理耗时3秒");

            }
            else if ("B".equals(previous)) {

                Thread.sleep(4000);
                System.out.println(Thread.currentThread().getName() + "对数据A的处理耗时3秒");

            }
            // 两个对象必须在此处汇合，只有一个线程调用change方法是不会进行数据交换的
            this.object = this.exchanger.exchange(this.object);
            System.out.println(Thread.currentThread().getName() + "exchanged" + previous + "for"
             + this.object);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}
